<?php
/**
 * MVC Handler
 *
 * @author		Joachim Ruf
 * @copyright	Copyright (c) 2003-2013 Loresoft Software (http://www.loresoft.de)
 * @license		http://yapary.loresoft.de/lizenzbedingungen     New BSD License
 *
 * */


Class Yapary_MVC_SimpleMVC_Handler
{
	const MODEL_VIEW_CONTROLLER	= 'mvc';
	const VIEW_CONTROLLER		= 'vc';
	private $architecture		= 'mvc';
	private $exceptionLog		= false;

	private $oSqlConnector		= NULL;
	private $oRoute;
	private $oHeader;
	private $path;
	private $defaultTemplate;
	private $inputEncoding		= NULL;
	private $outputEncoding		= NULL;

	private $oModel;
	private $oView;
	private $oController;

	public $registry;


    /**
	* @desc Yapary_MVC_SimpleMVC_Handler
	*/
	function __construct(Yapary_Header_Header &$_oHeader, $_path, $_defaultTemplate = 'default.phtml', $_defaultRouteFilePath = 'xml/site.xml') {
		$this->oHeader				= &$_oHeader;
		$this->path					= $_path;
		$this->defaultTemplate		= $_defaultTemplate;
		$this->defaultRouteFilePath	= $_defaultRouteFilePath;

		try {
			$this->oRoute			= new Yapary_Route_XmlRoute(file_get_contents($_defaultRouteFilePath));
		} catch (Exception $e) {
			throw $e;
		}
	}


	/**
	 * Definiert die zu verwendende Architekture
	 * @param string $_architecture	: {mvc|vc}
	 * */
	public function setArchitecture ($_architecture) {
		$this->architecture			= $_architecture;
	}


	/**
	 * Definiert die zu verwendende Architekture
	 * @param string $_architecture	: {mvc|vc}
	 * */
	public function setSqlConnector (Yapary_Db_Sql_Connector $_oSqlConnector) {
		$this->oSqlConnector		= $_oSqlConnector;
	}


	/**
	 * Definiert die zu verwendende Architekture
	 * @param string $_architecture	: {mvc|vc}
	 * */
	public function enableExceptionLog ($_enable = true) {
		if (!is_bool($_enable)) {
			return false;
		}

		return $this->exceptionLog	= $_enable;
	}


	/**
	 * MVC laden
	 * @return string
	 * */
	public function run(array $_arrParam = array(), $_controller = NULL)
	{
		// Vorbereitung
		$arrRef				= array();
		$arrRoute			= $this->getArrRoute();
		if ($_controller === NULL) { // Ermittel die Route automatisch
			$_controller		= $this->oRoute->getController($arrRoute['route']);

			if ($_controller == NULL) { // Wenn Kein Controller gefunden werden konnte, lade Fehlerroute und logge das Problem
				$_controller	= 'Failure_Failure'; // Fehlerroute laden
				if ($this->exceptionLog) {
					$oExceptionLogHandler	= new Yapary_Exception_ExceptionLogHandler($this->oSqlConnector);
					$oExceptionLogHandler->add('Missing Controller');
				}
//				return NULL;
			}
		}

		if (!defined('MVC_CONTROLLER')) {
			define('MVC_CONTROLLER', $_controller);
		}

		if ($this->oSqlConnector === NULL) {
			if ($this->exceptionLog) {
				$oExceptionLogHandler	= new Yapary_Exception_ExceptionLogHandler($this->oSqlConnector);
				$oExceptionLogHandler->add('Missing SQL Connector. Please use setSqlConnector() before run()');
			}
			throw new Exception('Missing SQL Connector. Please use setSqlConnector() before run()');
		}

		try {
			$oMetatag		= new Yapary_Header_Metatag();
		} catch (Exception $e) {
			if ($this->exceptionLog) {
				$oExceptionLogHandler	= new Yapary_Exception_ExceptionLogHandler($this->oSqlConnector);
				$oExceptionLogHandler->add('Error while initializing Yapary_Header_Metatag()');
			}
			throw $e;
		}
		try {
			$oHttp		= new Yapary_Header_Http();
		} catch (Exception $e) {
			if ($this->exceptionLog) {
				$oExceptionLogHandler	= new Yapary_Exception_ExceptionLogHandler($this->oSqlConnector);
				$oExceptionLogHandler->add('Error while initializing Yapary_Header_Http()');
			}
			throw $e;
		}
		try {
			$oOpenGraph		= new Yapary_Header_OpenGraph();
		} catch (Exception $e) {
			if ($this->exceptionLog) {
				$oExceptionLogHandler	= new Yapary_Exception_ExceptionLogHandler($this->oSqlConnector);
				$oExceptionLogHandler->add('Error while initializing Yapary_Header_OpenGraph()');
			}
			throw $e;
		}
		try {
			$oParameter		= new Yapary_Parameter_Parameter();
		} catch (Exception $e) {
			if ($this->exceptionLog) {
				$oExceptionLogHandler	= new Yapary_Exception_ExceptionLogHandler($this->oSqlConnector);
				$oExceptionLogHandler->add('Error while initializing Yapary_Parameter_Parameter()');
			}
			throw $e;
		}
		try {
			$oPartial		= new Yapary_MVC_SimpleMVC_Partial($this->path);
		} catch (Exception $e) {
			if ($this->exceptionLog) {
				$oExceptionLogHandler	= new Yapary_Exception_ExceptionLogHandler($this->oSqlConnector);
				$oExceptionLogHandler->add('Error while initializing Yapary_MVC_SimpleMVC_Partial');
			}
			throw $e;
		}


		/* @var $registry Yapary_MVC_SimpleMVC_Registry */
		$registry			= Yapary_MVC_SimpleMVC_Registry::getInstance();
		if (!$registry->isInitialized()) {
			$registry->initialize($this->oHeader, $oMetatag, $oHttp, $oOpenGraph, $this->oRoute, $this->oSqlConnector, $oParameter, $arrRoute);
		}
		$this->registry		= $registry;


		// MCV erstellen
		$this->oModel	= NULL;
		if ($this->architecture == self::MODEL_VIEW_CONTROLLER) {
			try {
				/* @var $oModel Yapary_MVC_SimpleMVC_IModel */
				$modelName			= $_controller.'Model';
				$this->oModel		= new $modelName();
			} catch (Exception $e) {
				throw $e;
			}
			if (!$this->oModel instanceof Yapary_MVC_SimpleMVC_IModel) {
				if ($this->exceptionLog) {
					$oExceptionLogHandler	= new Yapary_Exception_ExceptionLogHandler($this->oSqlConnector);
					$oExceptionLogHandler->add($ModelName.' have to implements Yapary_MVC_SimpleMVC_IModel');
				}
				throw new Exception ($ModelName.' have to implements Yapary_MVC_SimpleMVC_IModel');
			}
		}

		try {
			/* @var $oView Yapary_MVC_SimpleMVC_IView */
			$viewName			= $_controller.'View';
			$this->oView		= new $viewName($this->oModel, $oPartial, $arrRoute);
		} catch (Exception $e) {
			throw $e;
		}
		if (!$this->oView instanceof Yapary_MVC_SimpleMVC_IView) {
			if ($this->exceptionLog) {
				$oExceptionLogHandler	= new Yapary_Exception_ExceptionLogHandler($this->oSqlConnector);
				$oExceptionLogHandler->add($viewName.' have to implements Yapary_MVC_SimpleMVC_IView');
			}
			throw new Exception ($viewName.' have to implements Yapary_MVC_SimpleMVC_IView');
		}

		try {
			/* @var $this->oController Yapary_MVC_SimpleMVC_IController */
			$controllerName		= $_controller.'Controller';
			$this->oController	= new $controllerName($this->oView, $this->oModel, $oPartial, $arrRoute, $arrRef);
			$this->oController->setTemplate($this->defaultTemplate);
		} catch (Exception $e) {
			if ($this->exceptionLog) {
				$oExceptionLogHandler	= new Yapary_Exception_ExceptionLogHandler($this->oSqlConnector);
				$oExceptionLogHandler->add('Error while initializing '.$controllerName);
			}
			throw $e;
		}
		if (!$this->oController instanceof Yapary_MVC_SimpleMVC_IController) {
			if ($this->exceptionLog) {
				$oExceptionLogHandler	= new Yapary_Exception_ExceptionLogHandler($this->oSqlConnector);
				$oExceptionLogHandler->add($controllerName.' have to implements Yapary_MVC_SimpleMVC_IController');
			}
			throw new Exception ($controllerName.' have to implements Yapary_MVC_SimpleMVC_IController');
		}


		$useOutputCall = false;
		if ($this->inputEncoding !== NULL) {
			mb_http_input($this->inputEncoding);
			//mb_internal_encoding($this->inputEncoding);
			//mb_language('uni');
			//mb_regex_encoding('UTF-8');
			$useOutputCall = true;
		}
		if (isset($GLOBALS['outputEncoding'])) {
			mb_http_output($GLOBALS['outputEncoding']);
			$useOutputCall = true;
		}

		if ($useOutputCall === true) {
			ob_start('mb_output_handler');
		} else {
			ob_start();
		}

		//...->run() + forwarding;
		$this->oController->defaultAction($_arrParam);
		$forwarding				= (isset($arrRef['forwarding'])) ? $arrRef['forwarding'] : NULL;
		$this->defaultTemplate	= (isset($arrRef['template'])) ? $arrRef['template'] : NULL;

		if ($forwarding !== NULL) {
			ob_end_clean();
			return $this->run(array_merge($_arrParam, array('forwarding' => $_controller, 'arrRoute' => $arrRoute)), $forwarding);
		}

		if (isset($GLOBALS['contentType']) && isset($GLOBALS['outputEncoding'])) {
			header('Content-Type: '.$GLOBALS['contentType'].'; charset='.$GLOBALS['outputEncoding']); // Wichtig, damit die richtige output kodierung erstellt wird
		}
		if (isset($GLOBALS['contentType'])) { // Overwrite content type if specified in Controller
			header('Content-Type: '.$GLOBALS['contentType']);
		}

		try {
			$oTemplate		= new Yapary_MVC_SimpleMVC_Template($this->oView, $this->path, $arrRoute, $this->defaultTemplate);
		} catch (Exception $e) {
			if ($this->exceptionLog) {
				$oExceptionLogHandler	= new Yapary_Exception_ExceptionLogHandler($this->oSqlConnector);
				$oExceptionLogHandler->add('Error while initializing Yapary_MVC_SimpleMVC_Template');
			}
			throw $e;
		}

		$content = ob_get_contents();
		ob_end_clean();

		return $content;
	}


	/**
	 * @return Yapary_Route_XmlRoute
	 * */
	public function getRoute () {
		return $this->oRoute;
	}


	public function getArrRoute () {
		$_maxGetLength = 2000;

		// Url-Path und Parameter ermitteln und in arrRoute schreiben
		preg_match('/^\/(([a-z0-9-]{1,30}\.)*(de|at|com|net|org|eu|info|biz|name|co|to|us|ag|ws|be|cc|ch|li|it|lv|nu|ph|to|tv|co.uk|me.uk|org.uk|vu|sc|vc|as|mobi)\/)?([^?]{1,'.$_maxGetLength.'})?(\?([^#]{1,'.$_maxGetLength.'})?)?$/', $_SERVER['REQUEST_URI'], $arrRes);
		//echo'<pre>'.print_r($arrRes, true).'</pre>';
		$arrRoute['route']	= NULL;
		if (isset($arrRes[4])) { // Verzeichnisstruktur {name1/name2/name3}
			$arrRoute			= explode('/', $arrRes[4]);
			$arrRoute['route']	= $arrRes[4];
		}
		if (isset($arrRes[5])) { // PHP-Variablen {var1=1&var2=2&var3=3}
			$arrPhpVar	= explode('&', $arrRes[6]);
			$arrRoute['route']	= (isset($arrRes[6])) ? $arrRes[4].'?'.$arrRes[6] : '?'.$arrRes[6];
			if (count($arrPhpVar)) {
				while (list(,$string) = each($arrPhpVar)) {
					$arrTmp	= explode('=', $string);
					$name	= (isset($arrTmp[1])) ? $arrTmp[1] : NULL;
					$val	= $arrTmp[0];

					$_GET[$val]		= $name;
					$arrRoute[$val]	= $name;
				}
			}
		}

		return $arrRoute;
	}


	public function getDefaultTemplate () {
		return $this->defaultTemplate;
	}

	public function setInputEncoding ($_encoding) {
		$this->inputEncoding	= $_encoding;
	}

	public function setOutputEncoding ($_encoding, $_contentType = 'text/html') {
		$GLOBALS['outputEncoding']	= $_encoding;
		$GLOBALS['contentType']		= $_contentType;
	}


}


?>